package impl

import (
	"context"
	"github.com/redis/go-redis/v9"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/services/monitor/onlineuser"
	"go-caipu/pkg/setting"
	"go-caipu/pkg/util"
	"gorm.io/gorm"
	"time"
)

type store interface {
	Get(ctx context.Context, userID string) (*onlineuser.OnlineCommand, error)
	Set(ctx context.Context, cmd onlineuser.OnlineCommand, timeout int64) error
	Remove(ctx context.Context, userId string) error
	IsSessionValid(ctx context.Context, sessionID string) (bool, error)
}

type Service struct {
	store   store
	dbStore sqlStore
	cfg     *setting.Cfg
}

func ProvideService(cfg *setting.Cfg, db *gorm.DB) (*Service, error) {
	sqlStore := ProvideStore(db)
	s := &Service{
		store:   sqlStore,
		dbStore: sqlStore,
		cfg:     cfg,
	}

	if cfg.RedisConfig != nil {
		options := &redis.Options{
			Addr:     cfg.RedisConfig.Address,
			Username: cfg.RedisConfig.User,
			Password: cfg.RedisConfig.Password,
			DB:       util.StringToInt(cfg.RedisConfig.Database),
		}
		s.store = NewRedisStore(redis.NewClient(options), log.New("onlineuser.store"))
	}
	return s, nil
}

// Run 清理过期的登录记录
func (s Service) Run(ctx context.Context) error {
	ticker := time.NewTicker(time.Minute * 5)
	for {
		select {
		case <-ticker.C:
			s.dbStore.DeleteExpiredLogin(ctx, s.cfg.Jwt.Timeout)
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

func (s Service) GetOnlineUserPage(ctx context.Context, cmd onlineuser.GetOnlinePageCommand) (data []onlineuser.OnlineCommand, num int64, err error) {
	return s.dbStore.GetOnlineUserPage(ctx, cmd)
}

func (s Service) Get(ctx context.Context, token string) (*onlineuser.OnlineCommand, error) {
	return s.store.Get(ctx, token)
}

func (s Service) Set(ctx context.Context, cmd onlineuser.OnlineCommand) error {
	// 异步写到数据库供页面查询使用
	if s.cfg.RedisConfig != nil {
		go s.dbStore.Set(ctx, cmd, s.cfg.Jwt.Timeout)
	}
	return s.store.Set(ctx, cmd, s.cfg.Jwt.Timeout)
}

func (s Service) Remove(ctx context.Context, token string) error {
	// 异步写到数据库供页面查询使用
	if s.cfg.RedisConfig != nil {
		go s.dbStore.Remove(ctx, token)
	}
	return s.store.Remove(ctx, token)
}
func (s Service) IsSessionValid(ctx context.Context, token string) (bool, error) {
	// 异步写到数据库供页面查询使用
	if s.cfg.RedisConfig != nil {
		go s.dbStore.IsSessionValid(ctx, token)
	}
	return s.store.IsSessionValid(ctx, token)
}
